#-*- coding: utf-8 -*-
from util.Location import Location

#definisce la semantica per ogni chiave
comparators = ('EQ', 'NE', 'CONTAINS', 'NCONTAINS','GT', 'LT', 'GE', 'LE')
semanthic = {'id' : ['EQ', 'NE', 'CONTAINS'],
             'name' : ['EQ', 'NE', 'CONTAINS', 'NCONTAINS'],
             'lat' : ['EQ', 'NE', 'GT', 'LT', 'GE', 'LE'],
             'long' : ['EQ', 'NE', 'GT', 'LT', 'GE', 'LE'],
             'address' : ['CONTAINS'],
             'category' : ['EQ', 'NE', 'CONTAINS', 'NCONTAINS'],
             'opening' : ['CONTAINS', 'NCONTAINS'],
             'closing' : ['CONTAINS', 'NCONTAINS']}
                #non presenti nel protocollo 1.0 quindi non compatibili
                #'subcategory' : ['EQ', 'NE', 'CONTAINS', 'NCONTAINS'],
                #'note' : ['EQ', 'NE', 'CONTAINS', 'NCONTAINS'],
                #'tel' : ['EQ', 'NE', 'CONTAINS', 'NCONTAINS']}

'''
Restituisce tutte le locations che soddisfano il cofronto con il valore value.

@param key: campo della location sul quale si vuole eseguire il confronto
@param comp: tipo di confronto ('EQ', 'NE', 'CONTAINS', 'NCONTAINS','GT', 'LT', 'GE', 'LE')
@param value: valore da confrontare con quello della chiave
@param locations: Dizionario di location

@raise InvalidOperation: se si richiede un confronto numerico e il valore di value o 
                         dell'attributo key non è un decimale (float)
@raise ValueError: se non esiste il comparatore, o l'attributo key oppure se il comparatore
                   non è definito per l'attributo key
'''
def compare(key, comp, value, locations):
    key = key.lower()
    comp = comp.upper()
    #faccio il lower case per fare un controllo non key sensitive
    value = value.lower()
    res = {}
    #controllo l'esistenza del comparatore
    if not comp in comparators:
        raise ValueError('Invalid Comparator:%s' % comp)
    #controllo l'esistenza dell'attributo key in Location
    elif not key in Location().__dict__:
        raise ValueError('Invalid Key, Location not have attribute: %s' % key)
    #controllo che l'operazione comp sia definita per l'attriuto key
    elif not comp in semanthic.get(key, list()):
        raise ValueError('The Key %s not support the comparator %s' % (key,comp))
    #se i controlli precedenti sono andati a buon fine allora inizio ad eseguire i controlli
    else:
        for l in locations.values():
            #sfrutto la python introspection per prendere il valore dell'attributo dinamicamente
            #faccio il lower case per fare un controllo non key sensitive
            key_val = getattr(l, key)
            ##TODO dovrebbe funzionare solo con unicode
            if type(key_val) == str or type(key_val) == unicode:
                key_val = key_val.lower()
            if comp == 'EQ':
                if value == key_val:
                    res[l.id] = l
            elif comp == 'NE':
                if value != key_val:
                    res[l.id] = l
            elif comp == 'CONTAINS':
                if value in key_val:
                    res[l.id] = l
            elif comp == 'NCONTAINS':
                if value not in key_val:
                    res[l.id] = l
            elif comp == 'GT':
                if key_val > float(value):
                    res[l.id] = l
            elif comp == 'LT':
                if key_val < float(value):
                    res[l.id] = l
            elif comp == 'GE':
                if key_val >= float(value):
                    res[l.id] = l
            elif comp == 'LE':
                if key_val <= float(value):
                    res[l.id] = l
                 
    return res
    
    
